<?php
/**
 * Tokenizer API
 *
 * @version $Id: tokenizer.php 40 2008-07-20 01:03:48Z jacobsantos $
 */

/**
 * 
 *
 * @since 2.0
 */
class WP_Version_Tokenizer
{
	const TYPE_CONSTANT	= 1;
	const TYPE_GLOBAL	= 2;
	const TYPE_FUNCTION	= 4;
	const TYPE_METHOD	= 8;
	const TYPE_PROPERTY	= 16;
	const TYPE_CLASS	= 32;
	const TYPE_FILE		= 64;

	private $source = '';

	private $tokens = array();

	private $cleaned = array();

	public function __construct($source)
	{
		$this->source = $source;
		$this->tokens = token_get_all($source);
		$this->cleaned = $this->tokens;
	}

	public function strip_unneeded()
	{
		reset($this->cleaned);
		
		$source = '';
		$cleaned = array();
		while( false !== ($token = next($this->cleaned)) )
		{
			if (is_string($token)) {
				$cleaned[] = $token;
			} else {
				// token array
				list($id, $text, $line) = $token;

				if( ($id == T_COMMENT) || 
					($id == T_DOC_COMMENT) ||
					($id == T_ENCAPSED_AND_WHITESPACE) ||
					($id == T_INLINE_HTML)
				)
				{
					continue;
				}

				if($id == T_WHITESPACE)
				{
					$token[1] = " ";
					$source .= " ";
				}
				else
				{
					$source .= $text;
				}

				$cleaned[] = $token;
			}
		}
		
		$this->cleaned = $cleaned;
	}

	public function get_defined()
	{
		preg_match_all("/define\s*\(\s*(('|\")(.*?)('|\")\s*,\s*('|\")(.*?)('|\"))\s*\);/mi", $this->source, $matches);
		return $matches[3];
	}

	public function get_actions()
	{
		preg_match_all("/do_action\s*\(\s*(('|\")(.*?)('|\")\s*,\s*.*?)\s*\);/mi", $this->source, $matches);
		return array($matches[3], $matches[1]);
	}

	public function get_filters()
	{
		preg_match_all("/apply_filters\s*\(\s*(('|\")(.*?)('|\")\s*,\s*(.*?))\s*\);/mi", $this->source, $matches);
		return array($matches[3], $matches[1]);
	}

	public function get_globals()
	{
		preg_match_all("/global\s*(.*?);/mi", $this->source, $matches);
		return $matches[1];
	}

	public function get_class()
	{
		reset($this->cleaned);

		$source = '';
		$found = false;
		$items = array();
		$classes = array();
		$level = 0;

		$temp = array();

		$token = current($this->cleaned);
		do {
			if (is_string($token)) {
				if( $found === true )
				{
					if( $token == '{' )
						$level++;

					if( $token == '}' )
						$level--;

					if( $debug )
						echo $level."<br />";

					if( ($token == '}')  && ($level === 0) )
					{
						$found = false;
						$items[] = $token;
						$classes[] = new WP_Version_Tokenizer_ParseClass($items);
						$items = array();
						continue;
					}
				}

				if( true === $found )
				{
					$items[] = $token;
				}
				else
				{
					$temp[] = $token;
					$source .= $token;
				}
			}
			else
			{
				// token array
				list($id, $text) = $token;

				if( $id == T_CURLY_OPEN && ($found === true) )
				{
					$level++;
				}

				if( $id == T_CLASS )
				{
					$found = true;
					continue;
				}

				if( true === $found )
				{
					$items[] = $token;
				}
				else
				{
					$temp[] = $token;
					$source .= $text;
				}
			}
		} while( false !== ($token = next($this->cleaned)) );

		$this->cleaned = $temp;
		$this->source = $source;

		return $classes;
	}

	public function get_function()
	{
		preg_match_all("/function\s+&?\s*([_a-zA-Z0-9]+?)\s*\(.*?\)\s*\{/mi", $this->source, $matches);
		return array($matches[1], $matches[0]);
	}

	public function dump()
	{
		reset($this->cleaned);
		echo '<pre>';
		var_dump($this->cleaned);
		echo '</pre>';
	}
}

class WP_Version_Tokenizer_ParseClass
{
	public $cleaned = array();
	private $classname = '';

	public function __construct(array $tokens)
	{
		$this->cleaned = $tokens;

		if( is_string($classname) )
		{
			$this->classname = $classname;
		}
	}

	public function getClassName()
	{
		reset($this->cleaned);

		$classname = '';
		while( (empty($classname)) && (false !== ($token = next($this->cleaned))) )
		{
			if (is_array($token) && ($token[0] == T_STRING))
			{
				$classname = $token[1];
			}
		}
		return $classname;
	}

	public function getMethods()
	{
		reset($this->cleaned);

		$found = false;
		$items = array();
		$content = '';

		$token = current($this->cleaned);
		do
		{
			if (is_string($token)) {
				if( $token == '{' && ($found === true) )
				{
					$found = false;
					$items[] = $content;
					$content = '';
					continue;
				}

				if( true === $found )
				{
					$content .= $token;
				}
			}
			else
			{
				// token array
				list($id, $text) = $token;

				if( $id == T_FUNCTION )
				{
					$found = true;
					continue;
				}

				if( true === $found )
				{
					$content .= $text;
				}
			}
		} while( false !== ($token = next($this->cleaned)) );

		return $items;
	}

	public function getProperties()
	{
		reset($this->cleaned);

		$found = false;
		$items = array();
		$content = '';

		while( false !== ($token = next($this->cleaned)) )
		{
			if (is_string($token)) {
				if( $token == ';' && ($found === true) )
				{
					$found = false;
					$items[] = $content;
					$content = '';
					continue;
				}

				if( true === $found )
				{
					$content .= $token;
				}
			}
			else
			{
				// token array
				list($id, $text) = $token;

				if( $id == T_VAR )
				{
					$found = true;
					continue;
				}

				if( true === $found )
				{
					$content .= $text;
				}
			}
		}

		return $items;
	}

	public function dump()
	{
		reset($this->cleaned);
		echo '<pre>';
		var_dump($this->cleaned);
		echo '</pre>';
	}
}
